package com.hd.until;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

/**
 * Created by morris on 04/01/2017.
 */
public abstract class AbstractHttpClient implements HttpComponentClient<InnerHttpResponse> {

    public static Logger LOGGER = LoggerFactory.getLogger(AbstractHttpClient.class);

    protected String basePath;

    protected String url;
    
	protected String host;

	protected String schemeType;

	protected Integer port;

    protected CloseableHttpClient httpClient;

    protected Integer socketTimeout = 30000;

	protected Integer connectTimeout = 30000;

	protected Integer requestTimeout = 30000;

	protected Integer maxTotal;

	protected Integer maxPerRoute;

	protected Integer soTimeout;

	protected Integer inActivityTime;

	protected String charset;

	protected PoolingHttpClientConnectionManager connManager;
	
	public String getBasePath() {
		return basePath;
	}

	public void setBasePath(String basePath) {
		this.basePath = basePath;
	}

	public String getHost() {
		return host;
	}

	public void setHost(String host) {
		this.host = host;
	}

	public Integer getPort() {
		return port;
	}

	public void setPort(Integer port) {
		this.port = port;
	}

	public Integer getSocketTimeout() {
		return socketTimeout;
	}

	public void setSocketTimeout(Integer socketTimeout) {
		this.socketTimeout = socketTimeout;
	}

	public Integer getConnectTimeout() {
		return connectTimeout;
	}

	public void setConnectTimeout(Integer connectTimeout) {
		this.connectTimeout = connectTimeout;
	}

	public Integer getRequestTimeout() {
		return requestTimeout;
	}

	public void setRequestTimeout(Integer requestTimeout) {
		this.requestTimeout = requestTimeout;
	}

	public Integer getMaxTotal() {
		return maxTotal;
	}

	public void setMaxTotal(Integer maxTotal) {
		this.maxTotal = maxTotal;
	}

	public Integer getMaxPerRoute() {
		return maxPerRoute;
	}

	public void setMaxPerRoute(Integer maxPerRoute) {
		this.maxPerRoute = maxPerRoute;
	}

	public Integer getSoTimeout() {
		return soTimeout;
	}

	public void setSoTimeout(Integer soTimeout) {
		this.soTimeout = soTimeout;
	}

	public Integer getInActivityTime() {
		return inActivityTime;
	}

	public void setInActivityTime(Integer inActivityTime) {
		this.inActivityTime = inActivityTime;
	}

	public PoolingHttpClientConnectionManager getConnManager() {
		return connManager;
	}

	public String getCharset() {
		return charset;
	}

	public void setCharset(String charset) {
		this.charset = charset;
	}

	public String getSchemeType() {
		return schemeType;
	}

	public void setSchemeType(String schemeType) {
		this.schemeType = schemeType;
	}

	public InnerHttpResponse processPost(String path, Map<String, String> params, String content) {
        CloseableHttpResponse resp = null;
		try {
		    HttpUriRequest httpPost = constructHttpPost(path, params, content);
		    resp = httpClient.execute(httpPost);
            return processHttpResponse(resp);
		} catch (Exception e) {
			LOGGER.error("Process http Post error", e);
			return null;
		} finally {
			if (resp != null) {
				try {
					resp.close();
				} catch (IOException e) {
					LOGGER.error("Process http Post finally error", e);
				}
			}
		}
    }

    protected HttpPost constructHttpPost(String path, Map<String, String> params, String content) throws URISyntaxException, Exception {
		
    	URIBuilder uriBuilder = new URIBuilder().setScheme(schemeType).setHost(host).setPort(port).setPath(basePath + path);
//		for (String key : params.keySet()) {
//			String value = params.get(key);
//			if (value == null || value.length() == 0) {
//				continue;
//			}
//			uriBuilder.setParameter(key, params.get(key).toString());
//		}
		RequestConfig requestConfig =
                RequestConfig.custom()
                        .setSocketTimeout(socketTimeout)
                        .setConnectTimeout(connectTimeout)
                        .setConnectionRequestTimeout(requestTimeout)
                        .build();
		
		// TODO
        HttpPost httpPost  = null;
//        if (basePath.equals("/eff-uim-front-web")) {
//            httpPost = new HttpPost("https://quimf.hdfax.com/eff-uim-front-web" + path);
//        } else {
            httpPost = new HttpPost(uriBuilder.build());
//        }

		httpPost.setConfig(requestConfig);
		
		if (!CollectionUtils.isEmpty(params)) {
			// form
			List<NameValuePair> list = new ArrayList<NameValuePair>();
			Iterator<Entry<String, String>> iterator = params.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<String, String> elem = (Entry<String, String>) iterator.next();
				list.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
			}
			if (list.size() > 0) {
				UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(list, charset);
				httpPost.setEntity(formEntity);
			}
		}else{
        	//json
        	StringEntity httpEntity = new StringEntity(content, ContentType.APPLICATION_JSON);
        	httpPost.setEntity(httpEntity);
        }
		return httpPost;
	}

    
//    @Override
//    public InnerHttpResponse processPost(String path, Map<String, String> params, String content, HttpServletRequest request, Map<String, String> cookies) {
//        CloseableHttpResponse resp = null;
//		try {
//		    HttpUriRequest httpPost = constructHttpPost(path, params, content, request, cookies);
//		    resp = httpClient.execute(httpPost);
//		    // 保持金服向浏览器响应的会话
//		    for (Header header : resp.getHeaders("Set-Cookie")) {
//				LOGGER.info("header_response:name:{}, value{}", header.getName(), header.getValue());
//		    	if (header.getName().equals("Set-Cookie")) {
//		    		cookies.put("Cookie", header.getValue());
//				}
//		    }  
//		    
//            return processHttpResponse(resp);
//		} catch (Exception e) {
//			e.printStackTrace();
//			LOGGER.error("Process http Post error", e);
//			return null;
//		} finally {
//			if (resp != null) {
//				try {
//					resp.close();
//				} catch (IOException e) {
//					LOGGER.error("Process http Post finally error", e);
//				}
//			}
//		}
//    }
//
//    protected HttpPost constructHttpPost(String path, Map<String, String> params, String content, HttpServletRequest request, Map<String, String> cookies) throws URISyntaxException, Exception {
//		
//		RequestConfig requestConfig =
//                RequestConfig.custom()
//                        .setSocketTimeout(socketTimeout)
//                        .setConnectTimeout(connectTimeout)
//                        .setConnectionRequestTimeout(requestTimeout)
//                        .build();
//		
//		HttpPost httpPost = new HttpPost(url + basePath + path);
//		httpPost.setConfig(requestConfig);
//		
//		// 设置头部 以保持与浏览器会话
//		if (cookies.isEmpty()) {
//			httpPost.setHeader("Cookie", request.getHeader("Cookie"));
//		} else {
//			httpPost.setHeader("Cookie", cookies.get("Cookie"));
//		}
//
//		httpPost.setHeader("Content-Type", "application/json");
//		
//		if (!CollectionUtils.isEmpty(params)) {
//			// form
//			List<NameValuePair> list = new ArrayList<NameValuePair>();
//			Iterator<Entry<String, String>> iterator = params.entrySet().iterator();
//			while (iterator.hasNext()) {
//				Entry<String, String> elem = (Entry<String, String>) iterator.next();
//				list.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
//			}
//			if (list.size() > 0) {
//				UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(list, charset);
//				httpPost.setEntity(formEntity);
//			}
//		}else{
//        	//json
//        	StringEntity httpEntity = new StringEntity(content, ContentType.APPLICATION_JSON);
//        	httpPost.setEntity(httpEntity);
//        }
//		return httpPost;
//	}
    
    private static String tempCookIe = "";
	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	protected abstract InnerHttpResponse processHttpResponse(HttpResponse httpResp);
}
